Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Posix build #12

Merged
merged 34 commits into from Jan 20, 2018
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
980365a
Add CMakeLists.txt
marijnvdwerf Jan 20, 2018
b869def
Fix compilation with GCC on Linux
janisozaur Jan 20, 2018
252efea
Allow linking openloco on Linux with GCC
janisozaur Jan 20, 2018
5d6c32d
Add vanilla linker script
janisozaur Jan 20, 2018
7f91f41
Add more search dirs for OpenSUSE and similar distros
janisozaur Jan 20, 2018
e5cfd54
Add OpenLoco sections to i386 linker script
janisozaur Jan 20, 2018
e50b7b0
Link OpenLoco on Linux using customised linker script
janisozaur Jan 20, 2018
1e5ac2f
Force frame pointers for interop.cpp to allow optimised builds
janisozaur Jan 20, 2018
cbd1df6
Add support for using Boost::Filesystem
marijnvdwerf Jan 20, 2018
30214e7
Add missing imports
marijnvdwerf Jan 20, 2018
a14914c
Add WIN32 guards and start implementing platform
marijnvdwerf Jan 20, 2018
8a4c370
Move directory browsing to platform
marijnvdwerf Jan 20, 2018
66ea0fb
Fix remaining warnings
marijnvdwerf Jan 20, 2018
b52606b
Stub string conversion
marijnvdwerf Jan 20, 2018
5f08148
Add underscores to _OPENLOCO_USE_BOOST_FS_
IntelOrca Jan 20, 2018
db2f0f4
Fix MSVC
IntelOrca Jan 20, 2018
defb6cc
Pass correct boost::filesystem define
marijnvdwerf Jan 20, 2018
b569910
Fix compilation
marijnvdwerf Jan 20, 2018
f63796d
Set C++ standard through CMake
janisozaur Jan 20, 2018
08b2b52
Set Vista+ APIs for MinGW
janisozaur Jan 20, 2018
2e8a398
Use variable for linker script name
janisozaur Jan 20, 2018
350a596
Hide functions unused in Windows build
janisozaur Jan 20, 2018
eda81e9
Hide variable unused outside of Windows builds
janisozaur Jan 20, 2018
9b373eb
Remove unused functions
janisozaur Jan 20, 2018
b37c861
Add boost filesystem as option to cmake
janisozaur Jan 20, 2018
ef16105
Add missing Linux includes
janisozaur Jan 20, 2018
007e424
Fix compilation with GCC's C++17 filesystem
janisozaur Jan 20, 2018
b0cdc41
Set _NO_LOCO_WIN32_ for CMake builds
janisozaur Jan 20, 2018
73923b1
Own memory loaded via linker at all times
janisozaur Jan 20, 2018
1bff121
Don't include C sources
janisozaur Jan 20, 2018
b31f49b
Use variables for section files
marijnvdwerf Jan 20, 2018
21f9f1c
Remove setting redundant compilation flags in CMake
janisozaur Jan 20, 2018
4c37aed
Fix mprotected offset
janisozaur Jan 20, 2018
00a57f8
Add missing newline
janisozaur Jan 20, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
143 changes: 143 additions & 0 deletions CMakeLists.txt
@@ -0,0 +1,143 @@
cmake_minimum_required(VERSION 3.8)

set (PROJECT openloco)

project(${PROJECT})

if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt")
endif()

INCLUDE(FindPkgConfig)

set(USE_BOOST_FS_DEFAULT OFF)
if(APPLE)
set(USE_BOOST_FS_DEFAULT ON)
endif()

option(USE_BOOST_FILESYSTEM "Use Boost filesystem instead of C++17" ${USE_BOOST_FS_DEFAULT})

if (APPLE)
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/opt/openssl/lib/pkgconfig")
endif (APPLE)

set(COMMON_COMPILE_OPTIONS "${COMMON_COMPILE_OPTIONS} -fstrict-aliasing -Werror -Wundef -Wmissing-declarations -Winit-self -Warray-bounds -Waddress -Wchar-subscripts -Wenum-compare")

set(OBJ_FORMAT "elf32-i386")
set(LINKER_SCRIPT "ld_script_i386.xc")


# Handle creating the rct2 text and data files on OS X and Linux
# See details in src/openrct2.c:openrct2_setup_rct2_segment for how the values
# were derived.
if (UNIX)
set(OLOCO_EXE ${CMAKE_CURRENT_SOURCE_DIR}/loco.exe)
set(OLOCO_TEXT ${CMAKE_BINARY_DIR}/openloco_text)
set(OLOCO_DATA ${CMAKE_BINARY_DIR}/openloco_data)

add_custom_command(
OUTPUT ${OLOCO_TEXT}
COMMAND dd if="${OLOCO_EXE}" of="${OLOCO_TEXT}" bs=4096 skip=1 count=214
DEPENDS ${OLOCO_EXE}
)
add_custom_command(
OUTPUT ${OLOCO_DATA}
COMMAND dd if="${OLOCO_EXE}" of="${OLOCO_DATA}" bs=4096 skip=215 count=78
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marijnvdwerf can you double-check these offsets?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text start = 0x1000/4096 = 1
text size: 0xd6000/4096 = 214

rodata start: 0xd7000/4096 = 215
rodata+data size: (0x1f000+0x2f000)/4096 = 78

COMMAND dd if=/dev/zero of="${OLOCO_DATA}" bs=4096 seek=78 count=3133 conv=notrunc
DEPENDS ${OLOCO_EXE}
)
add_custom_target(segfiles DEPENDS ${OLOCO_TEXT} ${OLOCO_DATA})
if (APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sectcreate loco_text __text ${OLOCO_TEXT} -sectcreate loco_data __data ${OLOCO_DATA} -segaddr loco_data 0x4d7000 -segprot loco_data rwx rwx -segaddr loco_text 0x401000 -segprot loco_text rwx rwx -segaddr __TEXT 0x2000000 -read_only_relocs suppress")
else ()
# For Linux we have to use objcopy to wrap regular binaries into a linkable
# format. We use specific section names which are then referenced in a
# bespoke linker script so they can be placed at predefined VMAs.
add_custom_command(
OUTPUT openloco_text_section.o
COMMAND objcopy --input binary --output ${OBJ_FORMAT} --binary-architecture i386 ${OLOCO_TEXT} openloco_text_section.o --rename-section .data=.loco_text,contents,alloc,load,readonly,code
DEPENDS segfiles
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
add_custom_command(
OUTPUT openloco_data_section.o
COMMAND objcopy --input binary --output ${OBJ_FORMAT} --binary-architecture i386 ${OLOCO_DATA} openloco_data_section.o --rename-section .data=.loco_data,contents,alloc,load,readonly,data
DEPENDS segfiles
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
add_custom_target(linkable_sections DEPENDS openloco_text_section.o openloco_data_section.o)
set_source_files_properties(
openloco_text_section.o openloco_data_section.o
PROPERTIES
EXTERNAL_OBJECT true
GENERATED true
)
# can't use GLOB here, as the files don't exist yet at cmake-time
set(LOCO_SECTIONS "${CMAKE_BINARY_DIR}/openloco_data_section.o" "${CMAKE_BINARY_DIR}/openloco_text_section.o")
set(LOCO_SEGMENT_LINKER_FLAGS "-Wl,-T,\"${CMAKE_CURRENT_SOURCE_DIR}/distribution/linux/${LINKER_SCRIPT}\"")
endif ()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LOCO_SEGMENT_LINKER_FLAGS}")
endif (UNIX)

set(DEBUG_LEVEL 0 CACHE STRING "Select debug level for compilation. Use value in range 0–3.")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUG=${DEBUG_LEVEL}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG=${DEBUG_LEVEL}")

# include lib
include_directories("lib/")
# add source files
file(GLOB_RECURSE OLOCO_SOURCES "src/*.cpp" "src/*.h" "src/*.hpp")


if (APPLE)
file(GLOB_RECURSE OLOCO_MM_SOURCES "src/*.mm")
set_source_files_properties(${OLOCO_MM_SOURCES} PROPERTIES COMPILE_FLAGS "-x objective-c++ -fmodules")
endif ()

set(PIE_FLAG "-fno-pie")
set(TARGET_M "-m32")

# set necessary flags to compile code as is
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_M} -std=gnu99 ${COMMON_COMPILE_OPTIONS} -Wimplicit")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TARGET_M} ${COMMON_COMPILE_OPTIONS} -Wnon-virtual-dtor")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${TARGET_M}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS} ${TARGET_M} ${PIE_FLAG}")

PKG_CHECK_MODULES(SDL2 REQUIRED sdl2)
SET(SDL2LIBS ${SDL2_DEFINITIONS})

if (USE_BOOST_FILESYSTEM)
set(Boost_USE_STATIC_LIBS ON)
set(BOOST_INCLUDEDIR "/Users/Marijn/Downloads/boost_1_66_0")
set(BOOST_LIBRARYDIR "/Users/Marijn/Downloads/boost_1_66_0/stage/lib")
find_package(Boost COMPONENTS filesystem REQUIRED)
endif()

# Disable optimizations for interop.cpp for all compilers, to allow optimized
# builds without need for -fno-omit-frame-pointer
set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/src/openloco/interop/interop.cpp" PROPERTIES COMPILE_FLAGS -fno-omit-frame-pointer)

set(CMAKE_CXX_STANDARD 17)

add_executable(${PROJECT} ${OLOCO_SOURCES} ${OLOCO_MM_SOURCES} ${LOCO_SECTIONS})
target_link_libraries(${PROJECT} SDL2 ${SDL2LIBS})
add_dependencies(${PROJECT} segfiles)
target_compile_definitions(${PROJECT} PRIVATE _NO_LOCO_WIN32_=1)
if (USE_BOOST_FILESYSTEM)
target_link_libraries(${PROJECT} ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY})
target_compile_definitions(${PROJECT} PRIVATE _OPENLOCO_USE_BOOST_FS_=1)
else()
target_link_libraries(${PROJECT} stdc++fs)
endif()

if (MINGW)
target_compile_definitions(${PROJECT} PRIVATE _WIN32_WINNT=0x0600)
endif()

if (APPLE)
target_link_libraries(${PROJECT} "-framework Cocoa")
endif ()

if(EXISTS /Users/Marijn/Downloads/SDL2-2.0.7/build/libSDL2.dylib)
target_link_libraries(${PROJECT} /Users/Marijn/Downloads/SDL2-2.0.7/build/libSDL2.dylib "/Users/Marijn/Downloads/boost_1_66_0/stage/lib/libboost_filesystem.a")
endif()
218 changes: 218 additions & 0 deletions distribution/linux/ld_script_i386.xc
@@ -0,0 +1,218 @@
/* This script is based on elf_i386.xc from binutils 2.29.1-2 (Arch Linux)
with modifications for OpenLoco */
/* Script for -z combreloc: combine and sort reloc sections */
/* Copyright (C) 2014-2017 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
"elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SEARCH_DIR("/usr/i386-pc-linux-gnu/lib32"); SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib32"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/lib32"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/usr/local/lib32"); SEARCH_DIR("/usr/i386-pc-linux-gnu/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/lib32");
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x010000)); . = SEGMENT_START("text-segment", 0x010000) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.dyn :
{
*(.rel.init)
*(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
*(.rel.fini)
*(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
*(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*)
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
*(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
*(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
*(.rel.ctors)
*(.rel.dtors)
*(.rel.got)
*(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
*(.rel.ifunc)
}
.rel.plt :
{
*(.rel.plt)
PROVIDE_HIDDEN (__rel_iplt_start = .);
*(.rel.iplt)
PROVIDE_HIDDEN (__rel_iplt_end = .);
}
.init :
{
KEEP (*(SORT_NONE(.init)))
}
.plt : { *(.plt) *(.iplt) }
.plt.got : { *(.plt.got) }
.plt.sec : { *(.plt.sec) }
.loco_text 0x401000 : { *(.loco_text) }
.loco_data : { *(.loco_data) }
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
}
.fini :
{
KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table
.gcc_except_table.*) }
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges
.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
.got : { *(.got) *(.igot) }
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 12 ? 12 : 0, .);
.got.plt : { *(.got.plt) *(.igot.plt) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
. = .;
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(32 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) }
.debug_addr 0 : { *(.debug_addr) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}