From c424edd8ef7a7e4b5574fbacbccb159d9c41c2aa Mon Sep 17 00:00:00 2001 From: Akos Kiss Date: Sun, 11 Sep 2016 00:04:57 +0200 Subject: [PATCH] Improve the linking of libraries Although both jerry-libc and jerry-libm have configuration options that enable/disable their build, in practice, only jerry-libc can be replaced with the system (compiler-default) libc. If jerry-libm is disabled, the build of jerry-main fails, as there is no way to instruct the linker to link the system libm to the binary. (The build system does have a way to pass flags to the linker, but those flags are listed before the linked objects. For the references to get resolved correctly, the libraries to be linked have to be specified _after_ the objects.) This patch adds the EXTERNAL_LINK_LIBS configuration option to CMakeLists, which ensures that the specified libraries get correctly passed to the linker. (E.g, replacing jerry-libm with system libm becomes possible with `JERRY_LIBM=OFF EXTERNAL_LINK_LIBS='-lm'`.) Additionally, the patch also makes the following related changes: * Removes the COMPILER_DEFAULT_LIBC configuration option, as it is (almost) always the opposite of JERRY_LIBC. Moreover, its name is misleading: its only role is to add `-nostdlib` to the linker flags. * Makes use of transitive library dependencies: if a library has another library as dependency, and it is linked to a binary, its dependency is linked as well. Thus, jerry-libc, jerry-libm, and any external libraries are added to jerry-core as dependency, and then only jerry-core is linked to executables (cmake will take care of the rest). * build.py and run-tests.py follow up the changes, along with some minor syntax changes. * Moves static linking option to global CMakeLists, as unit test binaries should be linked the same way as jerry-main. * Adds EXTERNAL_COMPILER_FLAGS and EXTERNAL_LINKER_FLAGS as last to the flag list, to allow user override of (nearly) anything. The patch speculatively follows up the build system changes in the mbed, riot-stm32f4, and zephyr targets. JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu --- CMakeLists.txt | 38 ++++++++++++++++-------------- docs/01.GETTING-STARTED.md | 4 ++-- jerry-core/CMakeLists.txt | 10 ++++++-- jerry-main/CMakeLists.txt | 27 ++------------------- targets/mbed/Makefile.mbed | 1 - targets/riot-stm32f4/Makefile.riot | 1 - targets/zephyr/Makefile.zephyr | 2 +- tests/unit/CMakeLists.txt | 14 +---------- tools/build.py | 14 +++++------ tools/run-tests.py | 3 +-- 10 files changed, 42 insertions(+), 72 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2eb589d0f4..5405f213e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,10 +31,10 @@ set(UNITTESTS OFF CACHE BOOL "Build unit tests?") # Optional build settings set(PORT_DIR "${CMAKE_SOURCE_DIR}/targets/default" CACHE STRING "Use default or external port?") -set(COMPILER_DEFAULT_LIBC OFF CACHE BOOL "Use compiler default libc?") set(ENABLE_LTO OFF CACHE BOOL "Enable LTO build?") set(ENABLE_ALL_IN_ONE ON CACHE BOOL "Enable all-in-one build?") set(ENABLE_STRIP ON CACHE BOOL "Enable stripping all symbols from release binary?") +set(ENABLE_STATIC_LINK ON CACHE BOOL "Enable static linking?") if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") @@ -45,11 +45,7 @@ if("${PLATFORM}" STREQUAL "DARWIN") set(ENABLE_ALL_IN_ONE "ON") set(JERRY_LIBC "OFF") set(JERRY_LIBM "OFF") - set(COMPILER_DEFAULT_LIBC "ON") -endif() - -if(JERRY_LIBC AND COMPILER_DEFAULT_LIBC) - message(FATAL_ERROR "JERRY_LIBC and COMPILER_DEFAULT_LIBC cannot be enabled at the same time") + set(ENABLE_STATIC_LINK "OFF") endif() # Status messages @@ -61,10 +57,10 @@ message(STATUS "JERRY_LIBM " ${JERRY_LIBM}) message(STATUS "JERRY_CMDLINE " ${JERRY_CMDLINE}) message(STATUS "UNITTESTS " ${UNITTESTS}) message(STATUS "PORT_DIR " ${PORT_DIR}) -message(STATUS "COMPILER_DEFAULT_LIBC " ${COMPILER_DEFAULT_LIBC}) message(STATUS "ENABLE_LTO " ${ENABLE_LTO}) message(STATUS "ENABLE_ALL_IN_ONE " ${ENABLE_ALL_IN_ONE}) message(STATUS "ENABLE_STRIP " ${ENABLE_STRIP}) +message(STATUS "ENABLE_STATIC_LINK " ${ENABLE_STATIC_LINK}) # Setup directories # Project binary dir @@ -111,6 +107,11 @@ set(CMAKE_C_FLAGS_RELEASE "-Os") jerry_add_compile_flags(${FLAGS_COMMON_ARCH}) jerry_add_flags(CMAKE_EXE_LINKER_FLAGS ${FLAGS_COMMON_ARCH}) +# Enable static build +if(ENABLE_STATIC_LINK) + jerry_add_link_flags("-static") +endif() + # LTO if(ENABLE_LTO) jerry_add_compile_flags(-flto) @@ -126,7 +127,7 @@ if(ENABLE_LTO) endif() # Define _BSD_SOURCE if we use default port and compiler default libc -if(${PORT_DIR} STREQUAL "${CMAKE_SOURCE_DIR}/targets/default" AND COMPILER_DEFAULT_LIBC) +if(${PORT_DIR} STREQUAL "${CMAKE_SOURCE_DIR}/targets/default" AND NOT JERRY_LIBC) set(DEFINES_JERRY ${DEFINES_JERRY} _BSD_SOURCE) endif() @@ -163,8 +164,8 @@ else() jerry_add_link_flags(-Wl,-z,noexecstack) endif() -# Turn off linking to compiler's default libc, in case jerry-libc or external is used -if(NOT COMPILER_DEFAULT_LIBC) +# Turn off linking to compiler's default libc, in case jerry-libc is used +if(JERRY_LIBC) jerry_add_link_flags(-nostdlib) endif() @@ -187,14 +188,6 @@ if(JERRY_LIBC) jerry_add_compile_flags(-Werror) endif() -if(DEFINED EXTERNAL_COMPILE_FLAGS) - jerry_add_compile_flags(${EXTERNAL_COMPILE_FLAGS}) -endif() - -if(DEFINED EXTERNAL_LINKER_FLAGS) - jerry_add_link_flags(${EXTERNAL_LINKER_FLAGS}) -endif() - # C jerry_add_compile_flags(-std=c99 -pedantic) @@ -203,6 +196,15 @@ if(ENABLE_STRIP AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") jerry_add_link_flags(-s) endif() +# External compiler & linker flags +if(DEFINED EXTERNAL_COMPILE_FLAGS) + jerry_add_compile_flags(${EXTERNAL_COMPILE_FLAGS}) +endif() + +if(DEFINED EXTERNAL_LINKER_FLAGS) + jerry_add_link_flags(${EXTERNAL_LINKER_FLAGS}) +endif() + # Jerry's libc if(JERRY_LIBC) add_subdirectory(jerry-libc) diff --git a/docs/01.GETTING-STARTED.md b/docs/01.GETTING-STARTED.md index 3dcf34f197..472f596827 100644 --- a/docs/01.GETTING-STARTED.md +++ b/docs/01.GETTING-STARTED.md @@ -58,13 +58,13 @@ The default libc is jerry-libc, but you can use compiler-default libc or an exte - compiler-default libc: ```bash -python tools/build.py --jerry-libc=off --compiler-default-libc=on +python tools/build.py --jerry-libc=off ``` - external libc: ```bash -python tools/build.py --jerry-libc=off --compiler-default-libc=off --compile-flag="-I/path/to/libc/include" +python tools/build.py --jerry-libc=off --compile-flag="-nostdlib -I/path/to/ext-libc/include" --link-lib="-lext-c" ``` **Add toolchain file** diff --git a/jerry-core/CMakeLists.txt b/jerry-core/CMakeLists.txt index 126443df09..95dfa071f7 100644 --- a/jerry-core/CMakeLists.txt +++ b/jerry-core/CMakeLists.txt @@ -201,13 +201,19 @@ add_library(${JERRY_CORE_NAME} STATIC ${SOURCE_CORE}) target_compile_definitions(${JERRY_CORE_NAME} PUBLIC ${DEFINES_JERRY}) target_include_directories(${JERRY_CORE_NAME} PUBLIC ${INCLUDE_CORE}) -if (JERRY_LIBC) +set(JERRY_LIBS ) + +if(JERRY_LIBC) + set(JERRY_LIBS ${JERRY_LIBS} jerry-libc) target_include_directories(${JERRY_CORE_NAME} SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/jerry-libc/include") endif() -if (JERRY_LIBM) +if(JERRY_LIBM) + set(JERRY_LIBS ${JERRY_LIBS} jerry-libm) target_include_directories(${JERRY_CORE_NAME} SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/jerry-libm/include") endif() +target_link_libraries(${JERRY_CORE_NAME} ${JERRY_LIBS} ${IMPORTED_LIB} ${EXTERNAL_LINK_LIBS}) + install(TARGETS ${JERRY_CORE_NAME} DESTINATION lib) install(FILES jerry-api.h jerry-port.h DESTINATION include) diff --git a/jerry-main/CMakeLists.txt b/jerry-main/CMakeLists.txt index bc40bc58d6..dee9198229 100644 --- a/jerry-main/CMakeLists.txt +++ b/jerry-main/CMakeLists.txt @@ -18,16 +18,10 @@ set(JERRY_NAME jerry) project (${JERRY_NAME} C) # Optional build settings -set(ENABLE_LINK_MAP OFF CACHE BOOL "Enable generating a link map file?") -set(ENABLE_STATIC_LINK ON CACHE BOOL "Enable static linking?") - -if("${PLATFORM}" STREQUAL "DARWIN") - set(ENABLE_STATIC_LINK "OFF") -endif() +set(ENABLE_LINK_MAP OFF CACHE BOOL "Enable generating a link map file?") # Status messages message(STATUS "ENABLE_LINK_MAP " ${ENABLE_LINK_MAP}) -message(STATUS "ENABLE_STATIC_LINK " ${ENABLE_STATIC_LINK}) # Sources # Jerry standalone @@ -42,11 +36,6 @@ if(ENABLE_LINK_MAP) endif() endif() -# Disable static build -if(ENABLE_STATIC_LINK) - set(LINKER_FLAGS_COMMON "-static ${LINKER_FLAGS_COMMON}") -endif() - # Get version information from git if(IS_DIRECTORY "${CMAKE_SOURCE_DIR}/.git") execute_process(COMMAND git rev-parse --short HEAD @@ -67,18 +56,6 @@ target_compile_definitions(${JERRY_NAME} PRIVATE ${DEFINES_JERRY}) target_include_directories(${JERRY_NAME} PRIVATE ${PORT_DIR}) link_directories(${CMAKE_BINARY_DIR}) -set(JERRY_LIBS jerry-core) - -if(JERRY_LIBM) - set(JERRY_LIBS ${JERRY_LIBS} jerry-libm) -endif() - -if(JERRY_LIBC) - set(JERRY_LIBS ${JERRY_LIBS} jerry-libc) -endif() - -set(JERRY_LIBS ${JERRY_LIBS} ${IMPORTED_LIB}) - -target_link_libraries(${JERRY_NAME} ${JERRY_LIBS}) +target_link_libraries(${JERRY_NAME} jerry-core) install(TARGETS ${JERRY_NAME} DESTINATION bin) diff --git a/targets/mbed/Makefile.mbed b/targets/mbed/Makefile.mbed index e9430e6653..ef65ef3240 100644 --- a/targets/mbed/Makefile.mbed +++ b/targets/mbed/Makefile.mbed @@ -59,7 +59,6 @@ jerry: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain_external.cmake \ -DJERRY_LIBC=OFF \ -DJERRY_CMDLINE=OFF \ - -DCOMPILER_DEFAULT_LIBC=ON \ -DENABLE_ALL_IN_ONE=OFF \ -DEXTERNAL_CMAKE_SYSTEM_PROCESSOR=armv7l-hf \ -DEXTERNAL_CMAKE_C_COMPILER=arm-none-eabi-gcc \ diff --git a/targets/riot-stm32f4/Makefile.riot b/targets/riot-stm32f4/Makefile.riot index c9953f3535..b038a60b2f 100644 --- a/targets/riot-stm32f4/Makefile.riot +++ b/targets/riot-stm32f4/Makefile.riot @@ -35,7 +35,6 @@ libjerry: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain_external.cmake \ -DJERRY_LIBC=OFF \ -DJERRY_CMDLINE=OFF \ - -DCOMPILER_DEFAULT_LIBC=ON \ -DENABLE_ALL_IN_ONE=OFF \ -DEXTERNAL_CMAKE_SYSTEM_PROCESSOR=armv7l \ -DEXTERNAL_CMAKE_C_COMPILER=arm-none-eabi-gcc \ diff --git a/targets/zephyr/Makefile.zephyr b/targets/zephyr/Makefile.zephyr index 4adba15582..e46f701fe5 100755 --- a/targets/zephyr/Makefile.zephyr +++ b/targets/zephyr/Makefile.zephyr @@ -86,6 +86,7 @@ EXT_CFLAGS += -Werror=format -Werror=implicit-int -Wno-unused-but-set-variable EXT_CFLAGS += -Wno-main -Wno-strict-aliasing -Wno-old-style-declaration EXT_CFLAGS += -Wno-error=format= EXT_CFLAGS += -D_XOPEN_SOURCE=700 +EXT_CFLAGS += -nostdlib # Pass2 -include $(ZEPHYR_BASE)/scripts/Makefile.toolchain.$(ZEPHYR_GCC_VARIANT) @@ -127,7 +128,6 @@ endif -DEXTERNAL_CMAKE_C_COMPILER=$(CC) \ -DEXTERNAL_CMAKE_C_COMPILER_ID=GNU \ -DEXTERNAL_CMAKE_SYSTEM_PROCESSOR=$(CPU) \ - -DCOMPILER_DEFAULT_LIBC=OFF \ -DJERRY_CMDLINE=OFF \ -DEXTERNAL_COMPILE_FLAGS="$(EXT_CFLAGS)" \ -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain_external.cmake \ diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 37ef718905..8b0cdcc36c 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -36,19 +36,7 @@ foreach(SOURCE_UNIT_TEST_MAIN ${SOURCE_UNIT_TEST_MAIN_MODULES}) link_directories(${CMAKE_BINARY_DIR}) - set(JERRY_LIBS jerry-core) - - if(JERRY_LIBM) - set(JERRY_LIBS ${JERRY_LIBS} jerry-libm) - endif() - - if(JERRY_LIBC) - set(JERRY_LIBS ${JERRY_LIBS} jerry-libc) - endif() - - set(JERRY_LIBS ${JERRY_LIBS} ${IMPORTED_LIB}) - - target_link_libraries(${TARGET_NAME} ${JERRY_LIBS}) + target_link_libraries(${TARGET_NAME} jerry-core) add_dependencies(unittests ${TARGET_NAME}) endforeach() diff --git a/tools/build.py b/tools/build.py index 82918c56de..dccb266b7d 100755 --- a/tools/build.py +++ b/tools/build.py @@ -55,15 +55,15 @@ def devhelp(help): parser.add_argument('--snapshot-exec', metavar='X', choices=['on', 'off'], default='on', help='enable executing snapshot files (%(choices)s; default: %(default)s)') parser.add_argument('--cpointer-32bit', metavar='X', choices=['on', 'off'], default='off', help='enable 32 bit compressed pointers (%(choices)s; default: %(default)s)') parser.add_argument('--toolchain', metavar='FILE', action='store', default=default_toolchain(), help='add toolchain file (default: %(default)s)') - parser.add_argument('--cmake-param', metavar='OPTS', action='append', default=[], help='add custom arguments to CMake') - parser.add_argument('--compile-flag', metavar='OPTS', action='append', default=[], help='add custom compile flags') - parser.add_argument('--linker-flag', metavar='OPTS', action='append', default=[], help='add custom linker flags') + parser.add_argument('--cmake-param', metavar='OPT', action='append', default=[], help='add custom argument to CMake') + parser.add_argument('--compile-flag', metavar='OPT', action='append', default=[], help='add custom compile flag') + parser.add_argument('--linker-flag', metavar='OPT', action='append', default=[], help='add custom linker flag') + parser.add_argument('--link-lib', metavar='OPT', action='append', default=[], help='add custom library to be linked') parser.add_argument('--jerry-libc', metavar='X', choices=['on', 'off'], default='on', help='build and use jerry-libc (%(choices)s; default: %(default)s)') - parser.add_argument('--compiler-default-libc', metavar='X', choices=['on', 'off'], default='off', help='use compiler-default libc (%(choices)s; default: %(default)s)') parser.add_argument('--jerry-libm', metavar='X', choices=['on', 'off'], default='on', help='build and use jerry-libm (%(choices)s; default: %(default)s)') parser.add_argument('--jerry-cmdline', metavar='X', choices=['on', 'off'], default='on', help='build jerry command line tool (%(choices)s; default: %(default)s)') - parser.add_argument('--static-link', metavar='X', choices=['on', 'off'], default='on', help='enable static linking of jerry command line tool (%(choices)s; default: %(default)s)') - parser.add_argument('--strip', metavar='X', choices=['on', 'off'], default='on', help='strip release binary (%(choices)s; default: %(default)s)') + parser.add_argument('--static-link', metavar='X', choices=['on', 'off'], default='on', help='enable static linking of binaries (%(choices)s; default: %(default)s)') + parser.add_argument('--strip', metavar='X', choices=['on', 'off'], default='on', help='strip release binaries (%(choices)s; default: %(default)s)') parser.add_argument('--unittests', action='store_const', const='ON', default='OFF', help='build unittests') devgroup = parser.add_argument_group('developer options') @@ -88,7 +88,6 @@ def generate_build_options(arguments): build_options.append('-DJERRY_LIBC=%s' % arguments.jerry_libc.upper()) build_options.append('-DJERRY_LIBM=%s' % arguments.jerry_libm.upper()) build_options.append('-DJERRY_CMDLINE=%s' % arguments.jerry_cmdline.upper()) - build_options.append('-DCOMPILER_DEFAULT_LIBC=%s' % arguments.compiler_default_libc.upper()) build_options.append('-DCMAKE_VERBOSE_MAKEFILE=%s' % arguments.verbose) build_options.append('-DCMAKE_BUILD_TYPE=%s' % arguments.build_type) build_options.append('-DFEATURE_PROFILE=%s' % arguments.profile) @@ -113,6 +112,7 @@ def generate_build_options(arguments): build_options.append('-DEXTERNAL_COMPILE_FLAGS=' + ' '.join(arguments.compile_flag)) build_options.append('-DEXTERNAL_LINKER_FLAGS=' + ' '.join(arguments.linker_flag)) + build_options.append('-DEXTERNAL_LINK_LIBS=' + ' '.join(arguments.link_lib)) if arguments.toolchain: build_options.append('-DCMAKE_TOOLCHAIN_FILE=%s' % arguments.toolchain) diff --git a/tools/run-tests.py b/tools/run-tests.py index c9cdee8754..7a4c8892c6 100755 --- a/tools/run-tests.py +++ b/tools/run-tests.py @@ -91,8 +91,7 @@ def __init__(self, name = '', build_args = [], test_args = []): Options('buildoption_test-mem_stats', ['--mem-stats=on']), Options('buildoption_test-show_opcodes', ['--show-opcodes=on']), Options('buildoption_test-show_regexp_opcodes', ['--show-regexp-opcodes=on']), - Options('buildoption_test-jerry_libc', ['--jerry-libc=on', '--compiler-default-libc=off']), - Options('buildoption_test-compiler_default_libc', ['--compiler-default-libc=on', '--jerry-libc=off']), + Options('buildoption_test-compiler_default_libc', ['--jerry-libc=off']), ] def get_bin_dir_path(out_dir):