Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
CMake
CMake
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 3,193
    • Issues 3,193
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 16
    • Merge Requests 16
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • External Wiki
    • External Wiki
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • CMake
  • CMakeCMake
  • Issues
  • #17997

Closed
Open
Opened May 15, 2018 by Freddie Chopin@freddie.chopin

How to propagate file-level dependency (custom command + custom target) via interface library?

I have a following scenario:

  1. project I work on is mostly a static library
  2. as this is an embedded project I also have linker scripts
  3. each linker script requires some preprocessing before it can be used
  4. static library, include paths, compiler flags and the linker flag to use preprocessed linker script are propagated to users via interface library.

This generally works fine, however there's only target-level dependency between user's application and preprocessed linker script (via interface library). There is no file-level dependency, so when I modify the source of the linker script, the preprocessed linker script gets regenerated, however user's application is not relinked.

Here's a test case

$ ls
CMakeLists.txt  dummy.c  linker-script.ld-source  main.c

$ cat CMakeLists.txt 
cmake_minimum_required(VERSION 3.1)
project(a_test)

add_custom_command(OUTPUT linker-script.ld
		COMMAND cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/linker-script.ld-source linker-script.ld
		DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker-script.ld-source)
add_custom_target(linker-script DEPENDS linker-script.ld)

add_library(static-library STATIC
		dummy.c)

add_library(interface-library INTERFACE)
target_link_libraries(interface-library INTERFACE
		# -Tlinker-script.ld
		static-library)
add_dependencies(interface-library linker-script)

add_executable(application
		main.c)
target_link_libraries(application interface-library)

$ cat main.c 
int main(void)
{
	return 0;
}

dummy.c and linker-script.ld-source are just empty. Generated linker script is not actually used, but the commended fragment shows how I intend to use it. Let's run it:

$ mkdir output

$ cd output

$ cmake ..
-- The C compiler identification is GNU 8.1.0
-- The CXX compiler identification is GNU 8.1.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/cmake/output

$ make
Scanning dependencies of target static-library
[ 20%] Building C object CMakeFiles/static-library.dir/dummy.c.o
[ 40%] Linking C static library libstatic-library.a
[ 40%] Built target static-library
Scanning dependencies of target linker-script
[ 60%] Generating linker-script.ld
[ 60%] Built target linker-script
Scanning dependencies of target application
[ 80%] Building C object CMakeFiles/application.dir/main.c.o
[100%] Linking C executable application
[100%] Built target application

OK, everything seems fine. Now let's say that source of linker script is updated:

$ touch ../linker-script.ld-source

$ make
[ 40%] Built target static-library
[ 60%] Generating linker-script.ld
[ 60%] Built target linker-script
[100%] Built target application

As you see, the application is not relinked and this is a problem here. Any ideas how such scenario could be solved?

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: cmake/cmake#17997