CMake linking error with multilevel src directory - cmake

I'm having issues linking my project together using cmake.
The project consists of a library, "mylib", and an executable, "mybin", which is linked with it. The structure is the following:
.
├── CMakeLists.txt
├── include
│ ├── mylib.h
│ ├── entities
│ │ ├── entities.h
│ │ ├── entityA.h
│ │ └── entityB.h
│ └── shapes
│ ├── shapes.h
│ ├── shapeA.h
│ └── entityB.h
└── src
├── main.cpp
├── entities
│ ├── entityA.cpp
│ └── entityB.cpp
└── shapes
├── shapeA.cpp
└── entityB.cpp
Where mylib uses all .cpp and .h files (except from main.cpp) to create a static library, and mybin uses main.cpp and links with mylib.h. mylib.h pulls the other header files from the include directory.
Right now, my CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.13)
project(myproject VERSION 1.1.0 LANGUAGES C CXX)
add_library(mylib
src/entities/entityA.cpp
src/entities/entityB.cpp
src/shapes/shapeA.cpp
src/shapes/shapeB.cpp
include/mylib.h
include/entities/entities.h
include/entities/entitiesA.h
include/entities/entitiesB.h
include/shapes/shapes.h
include/shapes/shapeA.h
include/shapes/shapeB.h
)
target_include_directories(mylib PUBLIC include)
target_link_libraries(mylib PUBLIC)
target_compile_features(mylib PRIVATE cxx_std_11)
add_executable(mybin src/main.cpp)
target_link_libraries(mybin PRIVATE mylib)
target_compile_features(mybin PRIVATE cxx_std_11)
When I try to build my code, with
mkdir build
cd build
cmake ..
make
The library builds fine, but I get linking errors while the executable is building:
/usr/bin/ld: shapeA.cpp:(.text+0x344): undefined reference to `MyLib::Entities::EntityA::normalize_inplace()'
Not sure how to fix this, I tried to follow numeral tutorials and looking at other issues here and examples, but couldn't get to fix it. The actual code is in my github, in the "cmake" branch.
Thank you very much.
EDIT
The linking error I copied above is used in the src/shapes/shapeA.cpp file:
#include "shapes/shapeA.h"
#include <algorithm>
using MyLib::Entities::EntityA;
Mylib::Shapes::ShapeA::ShapeA() {}
Mylib::Shapes::ShapeA::~ShapeA(){}
bool Mylib::Shapes::ShapeA::intersect(const EntityA &entity) const {
const EntityA invdir = (EntityA(1.0, 1.0, 1.0) + entity).normalize_inplace();
return true;
}
It is defined in src/entities/entityA.cpp :
#include "entities/EntityA.h"
using MyLib::Entities::EntityA;
EntityA::EntityA(double a, double b, double c) :
a_(a), b_(b), c_(c) {}
EntityA::~EntityA(){}
EntityA EntityA::normalize_inplace(){
const double tot = std::sqrt(a_*a_ + b_*b_ + c_*c_);
a_ /= tot;
b_ /= tot;
c_ /= tot;
return EntityA(1.0, 1.0, 1.0);
}
EntityA EntityA::operator+(EntityA other) {
return EntiryA(a_ + other.a_, b_ + other.b_, c_ + other.c_);
}
There are many more linking errors like that one, I think nothing gets linked correctly at all.
Also, I used a makefile previously and all linking was being made correctly.

Related

How to test custom gradle plugin both with JUnit and manually in same sample project

My goal is to have this project setup:
example-gradle-plugin
├── build.gradle
└── src
├── main
│   ├── java
│   │   └── com ....
└── test
├── java
│   └── example
│   └── integrationtest
│ │ # GradleRunner.create().withProjectDir(testProjectPath.toFile()).withPluginClasspath()
│   └── SimpleProjectRegressionTest.java //
└── resources
└── simple
│ # plugins { id "example-gradle-plugin" }
├── build.gradle
│ # // includeBuild ../../../../example-gradle-plugin
└── settings.gradle
So the folder src/test/resources/simple is both used from a JUnit test, but as well can be used to run gradle commands from the command line using the composite build approach.
So this should work
cd src/test/resources/simple
gradle build
And this unit test should also work:
#Test
public void testBuildSample() {
final ClassLoader classLoader = ProjectSetupHelper.class.getClassLoader();
final Path sampleSourceRootPath = Paths.get(classLoader.getResource("simple").toURI());
final BuildResult result = GradleRunner.create()
.withProjectDir(sampleSourceRootPath.toFile())
.withArguments("build")
.withPluginClasspath()
.build();
}
However, there is a caveat when running JUnit, the custom-plugin-sources are referred to in 2 different ways at the same time:
GradleRunner.create().withProjectDir(testProjectPath.toFile()).withPluginClasspath() means to add project custom plugin files to the classpath for running the build during the unit test
In src/test/resources/simple/settings.gradle, the includeBuild ... command also refers to the custom plugin.
Is there an easier or cleaner way to achieve the above: Having a sample project with composite build that can be used from the commandline to verify local changes to the plugin, and using that sample project also in a unit test of the plugin?
Currently in the unit test I copy the sample folder to a temporary folder without settings.gradle to avoid such complications.
A little late to the party, but here is what I did.
I wrote a custom gradle plugin and was able to test it successfully with JUnit.
MyCustomPlugin.java
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.dsl.DependencyHandler;
public class MyCustomPlugin implements Plugin<Project>
{
#Override
public void apply(Project project)
{
DependencyHandler dependencyHandler = project.getDependencies();
dependencyHandler.add(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, "org.apache.commons:commons-lang3:3.12.0");
}
}
MyCustomPluginTest.java
import org.gradle.api.Project;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.Test;
import static org.gradle.internal.impldep.org.junit.Assert.assertTrue;
public class MyCustomPluginTest {
#Test
public void testCustomPlugin()
{
Project project = ProjectBuilder.builder().build();
// Java plugin required for IMPLEMENTATION task in the custom plugin
project.getPluginManager().apply("java");
project.getPluginManager().apply("com.mycustomplugin");
assertTrue(project.getPluginManager().hasPlugin("com.mycustomplugin"));
}
}
Sources:
https://docs.gradle.org/current/userguide/custom_plugins.html#sec:writing_tests_for_your_plugin
https://www.baeldung.com/gradle-create-plugin

Terraform Outputs across modules

I am struggling to work out how to pass outputs from a module and to consume it an another.
My folder structure:
.
├── main.tf
├── modules
│   ├── cloudwatch-event
│   │   ├── basic_event_rule.tf
│   │   ├── basic_event_target.tf
│   │   └── variables.tf
│   └── lambda
│      ├── basic_lambda.tf
│      ├── output.tf
│      ├── lambda.py
│      └── variables.tf
├── lambda
│   ├── main.tf
│   └── variables.tf
└── terraform.tfvar
In order to add scheduling to the lambda, i need to consume the Lambda ARN in to the CloudWatch module.
The lambda - basic_lambda.tf
resource "aws_lambda_function" "lambda_function" {
The lambda - outputs.tf
output "lambda_arn" {
value = "${aws_lambda_function.lambda_function.arn}"
In my lambda application module, i have this in my main lambda/main.tf
module "cloudwatch-event" {
source = "../modules/cloudwatch-event"
lambda_arn = "${module.lambda.lambda_arn}"
module "lambda" {
source = "../modules/lambda"
My lambda/variables.tf includes the lambda_arn variable as a string
variable "lambda_arn" {
type = "string"
}
The root main file looks like this:
provider "aws" {
region = var.aws_region
}
module "accesskey-lambda" {
source = "./lambda/"
}
Running TF i get this
Error: Missing required argument
on main.tf line 5, in module "accesskey-lambda":
5: module "accesskey-lambda" {
The argument "lambda_arn" is required, but no definition was found.
then adding it to the root main file doesnt resolve my issues.
Thanks
Nick
Solved, i had a typo
in the cloudwatch/basic_event_target.tf
arn = "${var.lambda_arn}"
Then in the cloudwatch/variable
variable "lambda_arn" {
type = string
}
The module then needed
module "cloudwatch-event" {
source = "../modules/cloudwatch-event"
lambda_arn = "${module.lambda.lambda_arn}"
}

How to add image from within 'content' subfolder - pelican

I got a structure
content/
├── applications
│   └── 2017
│   └── 08
│   └── 30
│   ├── article.md
│   └── forecast1.png
I want the img files to be same directories as the md files so that they can be put to:
ARTICLE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/index.html'
I have STATIC_PATHS = ['static_files','content'] however, the
[alt]({attach}applications/2017/08/30/forecast1.png)
gives error:
WARNING: Unable to find `applications/2017/08/30/forecast1.png`, skipping url replacement.
How can I include image into my md file in this simple case?
EDIT
so I changed the config applications is my category to:
PATH = 'content'
STATIC_PATHS = ['static_files','applications/2017/08/30/img', 'applications/2017/09/01/img']
ARTICLE_PATHS = ['applications', 'cat2', 'cat3']
I also added the ! before the [alt]() and still the images are not copied over to output.
EDIT2
iT WORKS WHEN APPLY EDIT ABOVE AND CHANGE ({attach}img/forecast1.png)
This works for me (following this):
content/
├── p001
│ └── myArticle001.md
│ └── img001
│ └── myPic1.png
│ └── myPic2.png
├── p002
│ └── myArticle002.md
│ └── img002
│ └── myPic1.png
│ └── myPic2.png
In pelicanconfig.py set:
PATH = 'content'
STATIC_PATHS = ['p001','p002']
ARTICLE_PATHS = STATIC_PATHS
In the md-files set:
![pic_A1]({attach}img001/myPic1.png)
![pic_A2]({attach}img001/myPic2.png)
and
![pic_B1]({attach}img002/myPic1.png)
![pic_B2]({attach}img002/myPic2.png)
Probabley you missed a ! only at the begin of the command. So you might try this:
![alt]({attach}applications/2017/08/30/forecast1.png)
Or try this:
PATH = 'content'
STATIC_PATHS = ['applications']
ARTICLE_PATHS = STATIC_PATHS
...
![alt]({attach}2017/08/30/forecast1.png)

addCSS not working in PrestaShop, for ModuleAdminController

I'm busy creating an Admin module and extending the ModuleAdminController class. I'm trying to add some CSS by using the following:
class AdminPrintspecJobsController extends ModuleAdminController
{
public function setMedia()
{
parent::setMedia();
$this->addCss(_MODULE_DIR_ . $this->module->name . "/css/printspec_table.css");
}
// ...
}
When I refresh my admin page, in Chrome, the Network panel indicates the file is added to the DOM, but it fails with an HTTP 404, not found error.
My folder structure looks as follows:
.
├── AdminTab.gif
├── config.xml
├── controllers
│ └── admin
│ ├── AdminPrintspecJobs.php
│ └── AdminTab.php
├── css
│ └── printspec_table.css
├── printspec.php
└── views
└── templates
└── admin
└── printspec_jobs
└── jobs.tpl
What am I doing wrong here?
I've managed to get it working by turning Friendly URLs off and then on again.

cmake undefined reference to function

The project structure below is a simplified example. I tried to boil it down to the minimal amount of files to reproduce my issue.
.
├── CMakeLists.txt
├── subdir1
│   ├── CMakeLists.txt
│   └── subsubdir1
│   ├── CMakeLists.txt
│   ├── Example.cpp
│   └── Example.h
└── subdir2
├── CMakeLists.txt
├── main.cpp
└── subsubdir1
├── CMakeLists.txt
├── ExampleCreator.cpp
└── ExampleCreator.h
./CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(test)
macro(add_sources)
file (RELATIVE_PATH _relPath "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
foreach (_src ${ARGN})
if (_relPath)
list (APPEND SRCS "${_relPath}/${_src}")
else()
list (APPEND SRCS "${_src}")
endif()
endforeach()
if (_relPath)
# propagate SRCS to parent directory
set (SRCS ${SRCS} PARENT_SCOPE)
endif()
endmacro()
add_subdirectory(subdir1)
add_subdirectory(subdir2)
add_executable(test ${SRCS})
subdir1/CMakeLists.txt
add_subdirectory(subsubdir1)
subdir1/subsubdir1/CMakeLists.txt
add_sources(Example.cpp)
subdir1/subsubdir1/Example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Example
{
public:
Example();
virtual ~Example();
};
#endif
subdir1/subsubdir1/Example.cpp
#include <stdio.h>
#include "Example.h"
Example::Example()
{
printf("Inside Example constructor\n");
}
Example::~Example()
{
}
subdir2/CMakeLists.txt
add_subdirectory(subsubdir1)
add_sources(main.cpp)
subdir2/main.cpp
#include "subsubdir1/ExampleCreator.h"
int main(int argc, char** argv)
{
ExampleCreator creator;
return 0;
}
subdir2/subsubdir1/CMakeLists.txt
add_sources(ExampleCreator.cpp)
subdir2/subsubdir1/ExampleCreator.h
#ifndef EXAMPLE_CREATOR_H
#define EXAMPLE_CREATOR_H
class ExampleCreator
{
public:
ExampleCreator();
virtual ~ExampleCreator();
};
#endif
subdir2/subsubdir1/ExampleCreator.cpp
#include "ExampleCreator.h"
#include "../../subdir1/subsubdir1/Example.h"
ExampleCreator::ExampleCreator()
{
Example* ex1 = new Example();
}
ExampleCreator::~ExampleCreator()
{
}
I'm hoping this is a really simple lack of understanding of how CMake handles dependencies. This compiles without error, but fails during linking. The make output below shows that Example.cpp isn't even compiling and I don't understand why.
user>:~/src/test/build$ make
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/subdir2/subsubdir1/ExampleCreator.cpp.o
[100%] Building CXX object CMakeFiles/test.dir/subdir2/main.cpp.o
Linking CXX executable test
CMakeFiles/test.dir/subdir2/subsubdir1/ExampleCreator.cpp.o: In function `ExampleCreator::ExampleCreator()':
ExampleCreator.cpp:(.text+0x2b): undefined reference to `Example::Example()'
collect2: ld returned 1 exit status
make[2]: *** [test] Error 1
make[1]: *** [CMakeFiles/test.dir/all] Error 2
make: *** [all] Error 2
All the sources are appended to the SRCS variable in the root CMakeLists.txt file from what I can tell. So, why isn't Example.cpp getting compiled? or linked?
The directory subdir1 doesn't generate a binary. Add this:
project(Example)
add_library(Example Example.cpp)
instead of your add_sources. After this, you need to tell the project that uses it to link against it:
TARGET_LINK_LIBRARIES(subdir2 Example)
If your names differ, document yourself on the functionalities of these commands.