How do I create a new compiler profile with Waf? - waf

I've found this very helpful page in the API docs of the Waf build system:
My wscript looks like this:
def options(opt):
opt.load('compiler_c')
def configure(conf):
from waflib.Tools.compiler_c import c_compiler
c_compiler['linux'] = ['mycc']
conf.load('compiler_c')
def build(bld):
bld.program(source='main.c', target='nop')
I've tried creating the file mycc.py, placing it in waflib/extras and recompiling Waf. However, when I try to configure my project using this new profile, I get the following error:
Setting top to : /home/user/waf/example
Setting out to : /home/user/waf/example/build
Checking for 'mycc' (c compiler) : not found
could not configure a c compiler!
(complete log in /home/user/waf/example/build/config.log)
I've also tried creating waflib/extras/mycc.py in the root of my project (the place where Waf is and from where it gets called). No good.
How do I do this?

Related

Calling Another Project's Controller From A Project In The Same Solution (.NET Core )

There are 2 projects in the same solution. First project is a .NET Core project and it has all the codes(controllers, models etc.) related to packages. I need to get the information (id, name, description) of the packages and display it in the second project(.NET Core Web App with Razor). Is it possible to do it without changing the first project? I only want to show the package list on a single web page.
I tried calling the first project's controller but it didn't work. Maybe I missed a point. Any help is appreciated.
This requirement can be achieved, please see the gif image below.
Tips
If you want to call another project's controller from a project in the same solution, you need to make sure there is in HomeController in both project. I mean the name of any class should be unique in both projects.
Otherwise you will face the same issue like my homepage.
Test Code:
public List<PackageReference> GetPackageList5(string projectname)
{
List<PackageReference> list = new List<PackageReference>();
PackageReference p = null;
XDocument doc = XDocument.Load(_webHostEnvironment.ContentRootPath+ "/"+ projectname + ".csproj");
var packageReferences = doc.XPathSelectElements("//PackageReference")
.Select(pr => new PackageReference
{
Include = pr.Attribute("Include").Value,
Version = pr.Attribute("Version").Value
});
Console.WriteLine($"Project file contains {packageReferences.Count()} package references:");
foreach (var packageReference in packageReferences)
{
p = new PackageReference();
p.Version= packageReference.Version;
p.Include= packageReference.Include;
list.Add(packageReference);
//Console.WriteLine($"{packageReference.Include}, version {packageReference.Version}");
}
return list;
}
My Test Steps:
create two project, Net5MVC,Net6MVC
add project reference.
My .net6 project references a .net5 project. So in my HomeController (.net), I add below:
using Net5MVC.ForCore6;
using Net5MVC.Models;
Suggestion
When we reference the .net5 project in .net6 project, we can build success, but when we deploy it, it always failed. The reason is some file was multiple publish output files with the same relative path.
Found multiple publish output files with the same relative path:
D:\..\Net6\Net6\Net5MVC\appsettings.Development.json,
D:\..\Net6\Net6\Net6MVC\appsettings.Development.json,
D:\..\Net6\Net6\Net5MVC\appsettings.json,
D:\..\Net6\Net6\Net6MVC\appsettings.json.
And usually will add class library to current project, not add a web project.
As we know we can find packages info in .csproj file, so we need copy and paste .csproj file to publish folder.
I still recommend using the GetPackageList5 method above as an interface for your project, using HttpClient for requests.

How to get a list of shared libraries used in the pipeline?

I can get all the libraries in Jenkins like this:
Jenkins.getInstance().getDescriptor("org.jenkinsci.plugins.workflow.libs.GlobalLibraries").getLibraries()
but it gives me all the libraries even if they are not used in the current project. I can see in the console log that only one of those libraries was loaded. How to get it's name?
Loading library name_of_the_library
It might not be the answer you were expecting but a simple solution would be to make a variable with the name of your library/ies and println it ?
def inst = Jenkins.getInstance()
def libs = inst.getDescriptor("org.jenkinsci.plugins.workflow.libs.GlobalLibraries").getLibraries()
for( lib in libs ) {
def lib_path = lib.getRetriever().getScm().getRemote()
}
But this gives me all the libraries, not only shared ones

Jenkins Shared Library - Importing classes from the /src folder in /vars

I am trying to writing a Jenkins Shared Library for my CI process. I'd like to reference a class that is in the \src folder inside a global function defined in the \vars folder, since it would allow me to put most of the logic in classes instead of in the global functions. I am following the repository structure documented on the official Jenkins documentation:
Jenkins Shared Library structure
Here's a simplified example of what I have:
/src/com/example/SrcClass.groovy
package com.example
class SrcClass {
def aFunction() {
return "Hello from src folder!"
}
}
/vars/classFromVars.groovy
import com.example.SrcClass
def call(args) {
def sc = new SrcClass()
return sc.aFunction()
}
Jenkinsfile
#Library('<lib-name>') _
pipeline {
...
post {
always {
classFromVars()
}
}
}
My goal was for the global classes in the /vars folder to act as a sort of public facade and to use it in my Jenkinsfile as a custom step without having to instantiate a class in a script block (making it compatible with declarative pipelines). It all seems pretty straightforward to me, but I am getting this error when running the classFromVars file:
<root>\vars\classFromVars.groovy: 1: unable to resolve class com.example.SrcClass
# line 1, column 1.
import com.example.SrcClass
^
1 error
I tried running the classFromVars class directly with the groovy CLI locally and on the Jenkins server and I have the same error on both environments. I also tried specifying the classpath when running the /vars script, getting the same error, with the following command:
<root>>groovy -cp <root>\src\com\example vars\classFromVars.groovy
Is what I'm trying to achieve possible? Or should I simply put all of my logic in the /vars class and avoid using the /src folder?
I have found several repositories on GitHub that seem to indicate this is possible, for example this one: https://github.com/fabric8io/fabric8-pipeline-library, which uses the classes in the /src folder in many of the classes in the /vars folder.
As #Szymon Stepniak pointed out, the -cp parameter in my groovy command was incorrect. It now works locally and on the Jenkins server. I have yet to explain why it wasn't working on the Jenkins server though.
I found that when I wanted to import a class from the shared library I have, to a script step in the /vars I needed to do it like this:
//thanks to '_', the classes are imported automatically.
// MUST have the '#' at the beginning, other wise it will not work.
// when not using "#BRANCH" it will use default branch from git repo.
#Library('my-shared-library#BRANCH') _
// only by calling them you can tell if they exist or not.
def exampleObject = new example.GlobalVars()
// then call methods or attributes from the class.
exampleObject.runExample()

importing dart code from other projects

** This question is edited and cleaned up some **
I have two projects and I want to use code from one in the other; I seem to be having trouble putting the code in the right directory structure to make the import statements work.
Both projects are created and managed exclusively from the Dart Editor on a Mac, if that makes any differences.
Project Directory Structures
Project 1: a command line app which contains the code I want to share in the following directory structure:
/dart/command_line_app
/lib
shared_library.dart
/bin
command_line_app.dart
Project 2: a web app which wants to import the code in shared_libary.dart
/dart/web_application
/packages
/web
web_application.dart
In the file shared_libary.dart, I declare it to be a library can create a simple class that provides output when instantiated:
library shared_library;
class ShareMe
{
ShareMe()
{
print("Hello, ShareMe");
}
}
This compiles, and works inside the command_line project: command_line_app.dart has the following:
import 'package:command_line_app/shared_library.dart';
void main() {
ShareMe shareMe = new ShareMe();
print("Hello, World!");
}
This imports the code runs, printing both "Hello Share Me," and Hello World.
THE PROBLEM
I want to instantiate the ShareMe class inside web_application.dart. I'd thought I could do that by putting in the same import statement I put in my command_line code:
import 'package:command_line_app/shared_library.dart';
But, when I put the same import into the web_appliation, it gets the error
Target of URI does not exist 'package:command_line_app/shared_library.dart'
Other Things I've Tried
I was certain I'd solved the problem when I cntrl-Clicked properties on Web_application and selected Project References.
It brings up a window allowing me to select command_line_app with a check box, but when I do, I get an error:
Could not set the project description for 'web_application' because the project description file (.project) is out of sync with the file system.
Whatever that means.
When I cntrl-click the underlined error and try Quick Fix it offers me "resolve dependencies" which sounds promising, but after a few seconds, it comes back and informs me that
Pub get failed, [1] Resolving dependencies... (15.3s)
Could not find package command_line_app at https://pub.dartlang.org.
Depended on by:
- web_application 0.0.0
I hope this is clear-er and gives a better insight into both what I'm trying to do and what I'm missing.
EDIT
you need to add
dependencies:
command_line_app:
path: ../command_line_app
to your dependencies in web_application/pubspec.yaml.
EDIT END
When you want to make code reusable in different packages, you should put that code into the lib directory of that package and import it using import 'package:mypackage/myfile.dart';.
Another problem you may face is, that browser applications can't import packages that have a dart:io dependency. If you want to reuse code between command line and browser applications you should move them into the lib directory of another package my_shared_code where you put only code that doesn't depend on dart:io (for example some entity classes) and import this code from both app packages (browser and command line).

Is is possible for my Waf wscript to call other wscripts in the current directory?

I am building a project with Waf. It has several third-party dependencies, and I would like to build each dependency from my main wscript. My project is organized like this:
/boost/
/gtest/
/source/
/waf
/wscript
/wscript_boost
/wscript_gtest
Each "dependency" wscript_* has commands defined, just like my main wscript.
def options(opt): pass
def configure(conf): pass
def build(bld): pass
If I had put the dependency wscript files in the dependency folders, I could just call opt.recurse('boost gtest'), but I don't want to mix my files with third-party files.
Is there any way for my wscript to call into wscript_boost and wscript_gtest?
I don't think it is possible in the current Waf implementation (waflib.Context.Context.recurse uses a global WSCRIPT_FILE variable).
Though ugly, it is possible to hack this at the beginning of your main wscript:
import waflib.Context
original_recurse = waflib.Context.Context.recurse
def new_recurse(ctx,*args, **kwargs):
original_wscript_file = waflib.Context.WSCRIPT_FILE
try:
waflib.Context.WSCRIPT_FILE = (original_wscript_file +
kwargs.pop('suffix', ''))
original_recurse(ctx, *args, **kwargs)
finally:
waflib.Context.WSCRIPT_FILE = original_wscript_file
waflib.Context.Context.recurse = new_recurse
Your main wscript would the be something like:
def configure(cfg):
cfg.recurse(suffix='_boost')
cfg.recurse(suffix='_gtest')
Note that there are some side effects, as WSCRIPT_FILE is suffixed when you are inside the wscript_boost file.
You can also submit an issue to the waf project.
The way to do that is usually to put a wscript into each subdirectory and to use recurse :
/boost/
/boost/wscript
/gtest/wscript
/source/
/waf
/wscript
And use recurse :
def build(bld):
# ...
bld.recurse("boost")
bld.recurse("gtest")
# ...

Resources